import 'dart:io';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:get/get_connect/http/src/status/http_status.dart';
import 'package:get_storage/get_storage.dart';
import 'package:nanoid/async.dart';
import 'package:work_tools/config/config.dart';
import 'package:work_tools/utils/utils.dart';
import 'api.dart';

// final String? tempAId = "77289A5EC1EDEB725AB1E7FCE3F8BE514091FEBE44315EC1AF6B410C415CA4E95728211641DC8DF8A7B7A7F18A080583D607E23761429C56114B335B518A0CE160668555C9D15008D47DE2E5F252BBD119BF4FA7EC93C83381EE3B897B5022097DC9315DAFDE24F70E48A12B40736C4FC5C8B47A3717DCAA77FE3655B70D1BA2B6909B099693D6F2326DB0B81B3D9E6F468FFF377540230C37FCE90586F54389968677B6FF97534A3D812AC059D4B0829FE5B29B2E9D4BA2AAA4D36B1682FEFE9EA54716F8C184AF0DEC4D9D8655655E";
// final String? tempRId = "77289A5EC1EDEB725AB1E7FCE3F8BE514091FEBE44315EC1AF6B410C415CA4E95728211641DC8DF8A7B7A7F18A080583D607E23761429C56114B335B518A0CE160668555C9D15008D47DE2E5F252BBD119BF4FA7EC93C83381EE3B897B5022097DC9315DAFDE24F70E48A12B40736C4FC5C8B47A3717DCAACAF16EA9EC3240FEB8E44179AC3E32C4FDEAB924AF99A4A248854761FA858F355A45678BDD3B71BD6E248A09C32D96EA9E8F1B9935BB9687E835A5B3A3F44CA7BA525184075FCA4144A75243C14F7FCA4D9CEA59C10416BE";

final String? tempAId = null;
final String? tempRId = null;

class LivanHttpException implements Exception {
  /// Creates a [PlatformException] with the specified error [code] and optional
  /// [message], and with the optional error [details] which must be a valid
  /// value for the [MethodCodec] involved in the interaction.
  LivanHttpException({
    required this.code,
    this.message,
    this.details,
    this.stacktrace,
  });

  final String code;
  final String? message;
  final dynamic details;
  final String? stacktrace;

  @override
  String toString() => 'LivanHttpException($code, $message, $details, $stacktrace)';
}

class Http {
  static Dio init() {
    var dio = Dio();
    // 网络配置
    dio.options.baseUrl = AppConfig.baseUrl;
    dio.options.connectTimeout = const Duration(milliseconds: AppConfig.connectTimeout);// = AppConfig.connectTimeout;
    dio.options.receiveTimeout = const Duration(milliseconds: AppConfig.receiveTimeout);// AppConfig.receiveTimeout;
    dio.options.headers["service-version"] = AppConfig.appVersion;
    dio.options.headers["signInSource"] = Platform.isIOS ? 'client_ios' : 'client_android';
    dio.options.headers["x-App-Id"] = AppConfig.APP_ID;
    dio.options.validateStatus = (status) {
      final isOk = status == HttpStatus.ok;
      final isTemporaryRedirect = status == HttpStatus.temporaryRedirect;
      return isOk || isTemporaryRedirect;
    };
    final proxyEnable = GetStorage().read<bool?>(AppConfig.TEST_PROXY_ENABLE) ?? false;
    final host = GetStorage().read<String?>(AppConfig.TEST_PROXY_HOST)?.toString() ?? "";
    final port = GetStorage().read<String?>(AppConfig.TEST_PROXY_PORT)?.toString() ?? "";
    if (proxyEnable && host.isNotEmpty && port.isNotEmpty) {
      dio.httpClientAdapter = IOHttpClientAdapter(
        createHttpClient: () {
          final client = HttpClient();
          client.findProxy = (uri) {
            // 将请求代理至 localhost:8888。
            // 请注意，代理会在你正在运行应用的设备上生效，而不是在宿主平台生效。
            return "PROXY $host:$port";
          };
          return client;
        },
      );
    }
    // 配置拦截器
    dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) async {
      options.headers["X-Sequence-No"] = await nanoid();
      options.headers["X-Timestamp"] = DateTime.now().microsecondsSinceEpoch;
      return handler.next(options);
    }, onResponse: (response, handler) async {
      final isRedirectStatus = response.statusCode == HttpStatus.temporaryRedirect;
      final location = response.headers['location'] ?? [];
      final hasLocation = location.isNotEmpty;
      if(isRedirectStatus && hasLocation) {
        Options options = Options(
          method: response.requestOptions.method,
          headers: response.requestOptions.headers,
          sendTimeout: response.requestOptions.sendTimeout,
          receiveTimeout: response.requestOptions.receiveTimeout,
        );
        final path = (response.headers['location'] ?? []).first;
        final data = Utils.syncData(response.requestOptions.data);
        final queryParameters = response.requestOptions.queryParameters;
        try {
          final newResponse = await dio.request(
            path,
            options: options,
            queryParameters: queryParameters,
            data: data,
          );
          return handler.next(newResponse);
        } catch (e) {
          rethrow;
        }
      }
      return handler.next(response);
    }, onError: (DioError e, handler) {
      return handler.next(e);
    }));
    dio.interceptors.add(LogInterceptor(responseBody: true));
    return dio;
  }

  static loadToken() async {
    //token处理
    String? aid = GetStorage().read("aId");
    String? rid = GetStorage().read("rId");
    if (tempAId != null && tempRId != null) {
      aid = tempAId;
      rid = tempRId;
    }

    if (aid != null && rid != null) {
      await setToken(aid, rid);
    }
  }

  ///设置token
  static setToken(token, rToken) async {
    if (tempAId != null && tempRId != null) {
      token = tempAId;
      rToken = tempRId;
    }
    dio.options.headers.addAll({"aId": token});
    dio.options.headers.addAll({"rId": rToken});
    await GetStorage().write("aId", token);
    await GetStorage().write("rId", rToken);
  }

  static bool get isLogin => isLoginAction();
  static bool isLoginAction() {
    final validRId = dio.options.headers.containsKey("rId");
    final validAId = dio.options.headers.containsKey("aId");
    // LocalLog.d("http检测登录状态: validRId - ${validRId}, validAId - ${validAId}");
    return validRId && validAId;
  }

  static getAid() {
    if (isLogin) return dio.options.headers["aId"];
    return "";
  }

  static getRid() {
    if (isLogin) return dio.options.headers["rId"];
    return "";
  }

  ///清除授权 todo
  static clearAuthorization() async {
    await clearStorageAuthorization();
  }

  ///清除授权 todo
  static clearStorageAuthorization() async {
    var msg = "clear before: ${dio.options.headers.toString()};";
    dio.options.headers.remove("aId");
    dio.options.headers.remove("rId");
    msg += "clear after: ${dio.options.headers.toString()}";

    await GetStorage().remove("aId");
    await GetStorage().remove("rId");
    await GetStorage().remove("user");
  }
}

